package com.motu.monstercity.server.gate;

import com.motu.monstercity.module.common.servermanager.ServerManager;
import com.motu.monstercity.module.common.verticle.GmVerticle;
import com.motu.vertx.module.utility.main.MainService;
import com.motu.vertx.module.utility.toolset.Tool;
import com.motu.vertx.module.utility.vertx.VerticleTool;
import io.vertx.core.*;
import io.vertx.core.json.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class MainVerticle extends AbstractVerticle {

    private static final Logger logger = LoggerFactory.getLogger(MainVerticle.class);

    @Override
    public void start(Promise<Void> startPromise) throws Exception {

        // 需要在这里获取配置，在startVerticle中通过config()获取不到
        JsonObject config = config();
        // 启动入口方法
        AbstractVerticle startVerticle = new AbstractVerticle() {
            @Override
            public void start() {
                logger.info("Gate MainVerticle start");

                try {

                    // 初始化公共服务
					MainService.init(vertx, config);

                    // 初始化游戏基础配置数据
                    Future.await(initBaseData());

                    // 部署游戏业务Verticle
                    Future.await(deployVerticles());

                    logger.info("Gate MainVerticle start success!!!");
                    startPromise.complete();

                } catch (Throwable t) {
                    /** 虚拟线程返回错误需要用Throwable才可以捕捉到异常 **/
                    logger.error("Gate MainVerticle start error cause:{}", Tool.getException(t));
                    startPromise.fail(t);
                }

            }
        };

        // Run the verticle a on virtual thread
        vertx.deployVerticle(startVerticle, new DeploymentOptions().setThreadingModel(ThreadingModel.VIRTUAL_THREAD))
                .onComplete(res -> {
                    if (res.succeeded()) {
                        System.out.println("Gate startVerticle Deployment success id is: " + res.result());

						// 部署GmVerticle gm都要部署,用来重载,检测集群等（这个要最后部署，这样启动失败就无法检测集群）
						VerticleTool.deployVerticleIfNeeded(vertx, GmVerticle.class.getName(), VerticleTool.getDeploymentOptions("gm-verticle-instances", 1, ThreadingModel.VIRTUAL_THREAD));
                    } else {
                        System.out.println("Gate startVerticle Deployment failed:" + res.cause());
                    }
                });

    }

    /**
     * 初始化游戏基础配置数据
     */
    public Future<Void> initBaseData() {
        Promise<Void> promise = Promise.promise();
        List<Future> futureList = new ArrayList<>();
        ServerManager.init(futureList);// 初始化服务器信息
        SocketManager.init(vertx);// 初始化Socket连接管理器

        CompositeFuture.all(futureList).onComplete(hanler->{
            if (hanler.succeeded()) {
                promise.complete();
            } else {
                promise.fail(hanler.cause());
            }
        });
        return promise.future();
    }

    /**
     * 部署游戏业务Verticle
     */
    public Future<Void> deployVerticles() {
        Promise promise = Promise.promise();

        List<Future<?>> list = new ArrayList<>();
        list.add(VerticleTool.deployVerticleIfNeeded(vertx, WebsocketVerticle.class.getName(), VerticleTool.getDeploymentOptions("websocket-verticle-instances", 8, ThreadingModel.VIRTUAL_THREAD)));
        list.add(VerticleTool.deployVerticleIfNeeded(vertx, ReceiveVerticle.class.getName(), VerticleTool.getDeploymentOptions("receive-verticle-instances", 8, ThreadingModel.VIRTUAL_THREAD)));
        list.add(VerticleTool.deployVerticleIfNeeded(vertx, BroadcastVerticle.class.getName(), VerticleTool.getDeploymentOptions("broadcast-verticle-instances", 1, ThreadingModel.VIRTUAL_THREAD)));
        list.add(VerticleTool.deployVerticleIfNeeded(vertx, GateMonitorVerticle.class.getName(), VerticleTool.getDeploymentOptions("monitor-verticle-instances", 1, ThreadingModel.VIRTUAL_THREAD)));
        list.add(VerticleTool.deployVerticleIfNeeded(vertx, GateMonitor2Verticle.class.getName(), VerticleTool.getDeploymentOptions("monitor-verticle-instances", 1, ThreadingModel.VIRTUAL_THREAD)));
        list.add(VerticleTool.deployVerticleIfNeeded(vertx, CheckRepeatedLoginVerticle.class.getName(), VerticleTool.getDeploymentOptions("checkrepeated-verticle-instances", 1, ThreadingModel.VIRTUAL_THREAD)));
        list.add(VerticleTool.deployVerticleIfNeeded(vertx, HttpVerticle.class.getName(), VerticleTool.getDeploymentOptions("http-verticle-instances", 1, ThreadingModel.VIRTUAL_THREAD)));

        Future.all(list).onComplete(promise);

        return promise.future();
    }

}
